/*  File Name	: Logger.h
 *  Author		: Javie Pong
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2012-4-22
 *  Description:
 */

#ifndef LOGGER_H_
#define LOGGER_H_

#include <stdarg.h>
#include <iostream>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <vector>
#include "Lock.h"
#include <list>

enum LogType
{
	INFO_LOG = 1,
	DEBUG_LOG = 2,
	ERROR_LOG = 3
};

class DuplexList;
class MessageBlock;
class MsgBlockPool;

class Logger
{
public:
	struct FileInfo
	{
		FileInfo()
		{
			reset();
		}
		FILE *file;
		tm time;
		time_t write_time;
		char dir[64];
		void reset(void);
	};
	virtual ~Logger();

	static Logger *instance(void);

	static tm now_time(void);

	//get now time as format YYYY-MM-DD
	static std::string now_time_str(tm &t);

	static std::string now_time_str_sec(void);

	static int run_log_loop(void *p);

	 // initialize
	virtual int open(std::string log_sub_dir="",std::string log_dir="./log");

	/*
	 *	default pre-format:
	 *	if type==DEBUG_LOG	-----> "Debug >>(%P|%p|%T)"
	 *	if type==INFO_LOG		-----> "Info >>>(%P|%p|%T)"
	 *	if type==ERROR_Log	-----> "Error >>(%P|%p|%T)"
	 */
	void set_pre_format(LogType type,std::string pre_format);

	/*
	 * format arg:
	 * 	%P: pid
	 * 	%p: thread id
	 * 	%T: current time,format: yyyy-mm-dd hh:MM:ss
	 * 	%t: current timestamp
	 * 	%d: int
	 * 	%D: double
	 * 	%f: float
	 * 	%s: string,char*
	 * 	%l: long
	 * 	%L: unsigned long
	 * 	%@: point address
	 */
	virtual int log(LogType type,const char *format,...);

	void stop_logger(void);

private:
	Logger();

	int write_log_to_file(MessageBlock *mb);

	MessageBlock* parse_format(const char *format_str,va_list argp);

	int myvsprintf(char *buf, const char *format, ...);

	static Logger *instance_;
	static RT_MUTEX rt_mutex_;

	std::string debug_pre_;
	std::string info_pre_;
	std::string error_pre_;
	std::string log_dir_;
	std::string log_sub_dir_;

	FileInfo file_info_;
	DuplexList *log_list_;
	MsgBlockPool *msg_pool_;

	static bool is_stop_;
};

/*
 * format arg:
 * 	%P: pid
 * 	%p: thread id
 * 	%T: current time,format: yyyy-mm-dd hh:MM:ss
 * 	%t: current timestamp
 * 	%d: int
 * 	%D: double
 * 	%f: float
 * 	%s: string,char*
 * 	%l: long
 * 	%L: unsigned long
 * 	%@: point address
 *
 * 	as:
 * 	LOG((DEBUG_LOG,"GateService::open---->[ip:%s][port:%d]",this->conn_addr_,this->port_));
 */
#define LOG(X)\
	Logger::instance()->log X;

#endif /* LOGGER_H_ */
